//! 转换进度报告策略模块
//! 
//! 该模块提供了独立的进度报告策略，与具体的转换实现解耦。
//! 用户可以根据需要选择不同的进度报告策略。

use std::sync::Arc;

/// 转换进度报告trait
/// 
/// 这个trait定义了转换过程中进度报告的接口，与具体的转换实现无关。
pub trait ConversionProgressReporter: Send + Sync {
    /// 报告进度消息
    fn report_progress(&self, message: &str);
    
    /// 报告详细进度（当前进度、总进度、消息）
    fn report_detailed_progress(&self, current: u64, total: u64, message: &str);
    
    /// 完成进度报告
    fn finish_progress(&self, message: &str);
}

/// 转换进度报告策略trait
/// 
/// 这个trait定义了进度报告的策略，决定何时以及如何报告进度。
pub trait ConversionProgressStrategy: Send + Sync {
    /// 确定是否应该报告进度
    fn should_report_progress(&self, current: u64, total: u64) -> bool;
    
    /// 格式化进度消息
    fn format_progress_message(&self, current: u64, total: u64, message: &str) -> String;
    
    /// 确定是否应该报告开始消息
    fn should_report_start(&self, message: &str) -> bool;
    
    /// 确定是否应该报告完成消息
    fn should_report_finish(&self, message: &str) -> bool;
    
    /// 格式化开始消息
    fn format_start_message(&self, message: &str) -> String;
    
    /// 格式化完成消息
    fn format_finish_message(&self, message: &str) -> String;
}

/// 默认进度报告器（打印到控制台）
pub struct ConsoleProgressReporter;

impl ConsoleProgressReporter {
    pub fn new() -> Self {
        Self
    }
}

impl ConversionProgressReporter for ConsoleProgressReporter {
    fn report_progress(&self, message: &str) {
        println!("{}", message);
    }
    
    fn report_detailed_progress(&self, current: u64, total: u64, message: &str) {
        if total > 0 {
            let percent = (current * 100) / total;
            println!("{}% - {}", percent, message);
        } else {
            println!("{}", message);
        }
    }
    
    fn finish_progress(&self, message: &str) {
        println!("{}", message);
    }
}

/// 静默进度报告器（不输出任何信息）
pub struct SilentProgressReporter;

impl SilentProgressReporter {
    pub fn new() -> Self {
        Self
    }
}

impl ConversionProgressReporter for SilentProgressReporter {
    fn report_progress(&self, _message: &str) {
        // 静默，不输出任何信息
    }
    
    fn report_detailed_progress(&self, _current: u64, _total: u64, _message: &str) {
        // 静默，不输出任何信息
    }
    
    fn finish_progress(&self, _message: &str) {
        // 静默，不输出任何信息
    }
}

/// 只显示总进度的转换进度报告器（不显示每个分片的进度）
pub struct TotalOnlyConversionProgressReporter;

impl TotalOnlyConversionProgressReporter {
    pub fn new() -> Self {
        Self
    }
}

impl ConversionProgressReporter for TotalOnlyConversionProgressReporter {
    fn report_progress(&self, message: &str) {
        // 只显示关键进度信息
        if message.contains("开始") || message.contains("完成") {
            println!("{}", message);
        }
    }
    
    fn report_detailed_progress(&self, current: u64, total: u64, message: &str) {
        // 只在进度有显著变化时显示（每10%）
        if total > 0 {
            let percent = (current * 100) / total;
            let prev_percent = ((current - 1) * 100) / total;
            
            // 只在达到10%的倍数时显示进度
            if percent % 10 == 0 && (current == 1 || percent != prev_percent) {
                println!("{}% - {}", percent, message);
            }
        }
    }
    
    fn finish_progress(&self, message: &str) {
        println!("{}", message);
    }
}

/// 默认进度报告策略（显示所有进度）
pub struct DefaultProgressStrategy;

impl DefaultProgressStrategy {
    pub fn new() -> Self {
        Self
    }
}

impl ConversionProgressStrategy for DefaultProgressStrategy {
    fn should_report_progress(&self, _current: u64, _total: u64) -> bool {
        true // 总是报告进度
    }
    
    fn format_progress_message(&self, current: u64, total: u64, message: &str) -> String {
        if total > 0 {
            let percent = (current * 100) / total;
            format!("{}% - {}", percent, message)
        } else {
            message.to_string()
        }
    }
    
    fn should_report_start(&self, _message: &str) -> bool {
        true // 总是报告开始
    }
    
    fn should_report_finish(&self, _message: &str) -> bool {
        true // 总是报告完成
    }
    
    fn format_start_message(&self, message: &str) -> String {
        message.to_string()
    }
    
    fn format_finish_message(&self, message: &str) -> String {
        message.to_string()
    }
}

/// 只显示总进度的策略（不显示每个分片的进度）
pub struct TotalOnlyProgressStrategy;

impl TotalOnlyProgressStrategy {
    pub fn new() -> Self {
        Self
    }
}

impl ConversionProgressStrategy for TotalOnlyProgressStrategy {
    fn should_report_progress(&self, current: u64, total: u64) -> bool {
        // 只在关键进度点报告（每10%或完成时）
        if total > 0 {
            let percent = (current * 100) / total;
            let prev_percent = ((current - 1) * 100) / total;
            
            // 只在达到10%的倍数时显示进度或完成时
            percent % 10 == 0 && (current == 1 || percent != prev_percent) || current == total
        } else {
            current == 1 // 如果没有总数，只在开始时报告
        }
    }
    
    fn format_progress_message(&self, current: u64, total: u64, message: &str) -> String {
        if total > 0 {
            let percent = (current * 100) / total;
            format!("{}% - {}", percent, message)
        } else {
            message.to_string()
        }
    }
    
    fn should_report_start(&self, message: &str) -> bool {
        // 只显示关键开始信息
        message.contains("开始") || message.contains("启动")
    }
    
    fn should_report_finish(&self, message: &str) -> bool {
        // 总是报告完成信息
        message.contains("完成") || message.contains("结束")
    }
    
    fn format_start_message(&self, message: &str) -> String {
        message.to_string()
    }
    
    fn format_finish_message(&self, message: &str) -> String {
        message.to_string()
    }
}

/// 转换进度管理器
/// 
/// 这个管理器负责协调进度报告器和进度策略，提供统一的进度报告接口。
pub struct ConversionProgressManager {
    reporter: Arc<dyn ConversionProgressReporter>,
    strategy: Arc<dyn ConversionProgressStrategy>,
}

impl ConversionProgressManager {
    /// 创建新的进度管理器
    pub fn new(
        reporter: Arc<dyn ConversionProgressReporter>,
        strategy: Arc<dyn ConversionProgressStrategy>,
    ) -> Self {
        Self {
            reporter,
            strategy,
        }
    }
    
    /// 报告进度消息
    pub fn report_progress(&self, message: &str) {
        if self.strategy.should_report_start(message) {
            let formatted_message = self.strategy.format_start_message(message);
            self.reporter.report_progress(&formatted_message);
        }
    }
    
    /// 报告详细进度
    pub fn report_detailed_progress(&self, current: u64, total: u64, message: &str) {
        if self.strategy.should_report_progress(current, total) {
            let formatted_message = self.strategy.format_progress_message(current, total, message);
            self.reporter.report_detailed_progress(current, total, &formatted_message);
        }
    }
    
    /// 完成进度报告
    pub fn finish_progress(&self, message: &str) {
        if self.strategy.should_report_finish(message) {
            let formatted_message = self.strategy.format_finish_message(message);
            self.reporter.finish_progress(&formatted_message);
        }
    }
}

/// 进度报告工厂
/// 
/// 提供创建不同类型进度报告器和策略的便捷方法。
pub struct ProgressReporterFactory;

impl ProgressReporterFactory {
    /// 创建控制台进度报告器
    pub fn create_console_reporter() -> Arc<dyn ConversionProgressReporter> {
        Arc::new(ConsoleProgressReporter::new())
    }
    
    /// 创建静默进度报告器
    pub fn create_silent_reporter() -> Arc<dyn ConversionProgressReporter> {
        Arc::new(SilentProgressReporter::new())
    }
    
    /// 创建默认进度策略
    pub fn create_default_strategy() -> Arc<dyn ConversionProgressStrategy> {
        Arc::new(DefaultProgressStrategy::new())
    }
    
    /// 创建只显示总进度的策略
    pub fn create_total_only_strategy() -> Arc<dyn ConversionProgressStrategy> {
        Arc::new(TotalOnlyProgressStrategy::new())
    }
    
    /// 创建使用默认策略的控制台进度管理器
    pub fn create_default_console_manager() -> ConversionProgressManager {
        ConversionProgressManager::new(
            Self::create_console_reporter(),
            Self::create_default_strategy(),
        )
    }
    
    /// 创建使用总进度策略的控制台进度管理器
    pub fn create_total_only_console_manager() -> ConversionProgressManager {
        ConversionProgressManager::new(
            Self::create_console_reporter(),
            Self::create_total_only_strategy(),
        )
    }
}